/*
 * (C) 2009, Elephant Seven Hamburg Gmbh, 
 * Author: Detlev Wiese
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
 * use this file except in compliance with the License. You may obtain a copy 
 * of the License at
 *  
 *     http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.se and its accompanying notice file is
 * included with the distribution. 
 */
package com.e7.streams;

/**
 * Filtered stream are streams which suppress elements not matching a given
 * predicate.
 * 
 * @param <E> The type of the elements
 */
public class FilteredStream<E> extends ConcatenatedStream<E> 
  implements Stream<E> {
  
  /**
   * Create an instance!
   * 
   * @param predicate
   *          The predicate to evaluate for all elements. If the predicate is
   *          true, the element will be included in the resulting stream
   * @param stream
   *          The stream to filter
   */
  public FilteredStream(final Predicate<E> predicate, Stream<E> stream) {
    super(new MappedStream<Stream<E>, E>(stream,
        new MappingFunction<Stream<E>, E>() {
          // we reuse the single-element stream here!
          final SingleElementStream<E> singleElementStream = 
              new SingleElementStream<E>(null);

          public Stream<E> value(E object) {
            if (predicate.value(object)) {
              singleElementStream.initializeForElement(object);
              return singleElementStream;
            } else
              return Streams.emptyStream();
          }
        }));
  }

  /**
   * Syntactic sugar only! See
   * {@link FilteredStream#FilteredStream(Predicate, Stream)}.
   */
  public FilteredStream(Stream<E> stream, Predicate<E> predicate) {
    this(predicate, stream);
  }
}
